/**
  ******************************************************************************
  * File Name          : exio.c
  * Description        : 
  ******************************************************************************
  * @attention
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "route.h"
#include <string.h>

typedef enum
{
	RS422_RCVST_HEADER1  = 0,
	RS422_RCVST_HEADER2,
	RS422_RCVST_PLENGTH,
	RS422_RCVST_PAYLOAD,
	RS422_RCVST_CRCHECK,
}RS422_RecvStateType;

extern void RS422_Sendbuf(const uint8_t *buf, uint32_t len);

/* 422 接收消息队列 */
static Route_PayloadType route_rx_link422_isr;

/* 中断接收状态控制 */
static volatile RS422_RecvStateType rs422_isr_recvstate;

uint8_t RS422_LinkSend(const uint8_t *payload, uint8_t pllen)
{
	uint8_t i, check;
	uint8_t sendbuf[ROUTE_PAYLOAD_MAXLEN + 8];
  
  if(pllen > ROUTE_PAYLOAD_MAXLEN)
  {
    return 1;
  }
  
  memset(sendbuf, 0, pllen+4);
  
	sendbuf[0] = 0x5Au;
	sendbuf[1] = 0xA5u;
	
	sendbuf[2] = pllen;
	
	check = 0x00 + pllen;
	
	for(i=0; i<pllen; i++)
	{
		sendbuf[i+3] = payload[i];
		check += payload[i];
	}
	
	sendbuf[3+pllen] = check; /* check */

	RS422_Sendbuf(sendbuf, pllen+4);
  
  return 0;
}

void RS422_BreakIsr(void)
{
	rs422_isr_recvstate = RS422_RCVST_HEADER1;
}

void RS422_RecvIsr(uint8_t dat)
{
	static uint8_t count;
	static uint8_t check;
	
	switch(rs422_isr_recvstate)
	{
		case RS422_RCVST_HEADER1:
			if(dat == 0x5Au)
			{
				rs422_isr_recvstate = RS422_RCVST_HEADER2;
			}
			break;
		
		case RS422_RCVST_HEADER2:
			if(dat == 0xA5u)
			{
				rs422_isr_recvstate = RS422_RCVST_PLENGTH;
				check = 0;
			}
			else
			{
				rs422_isr_recvstate = RS422_RCVST_HEADER1;
			}
			break;
		
		case RS422_RCVST_PLENGTH:
			if(dat < ROUTE_PAYLOAD_MAXLEN)
			{
				route_rx_link422_isr.length = dat;
				check += route_rx_link422_isr.length;
				count = 0;
				rs422_isr_recvstate = RS422_RCVST_PAYLOAD;
			}
			else
			{
				rs422_isr_recvstate = RS422_RCVST_HEADER1;
			}
			break;
		
		case RS422_RCVST_PAYLOAD:
			route_rx_link422_isr.payload[count++] = dat;
			check += dat;
			if(count >= route_rx_link422_isr.length)
			{
				rs422_isr_recvstate = RS422_RCVST_CRCHECK;
			}
			break;

		case RS422_RCVST_CRCHECK:
			if(check == dat)
			{
				if(Route_RxLink422_Qhd != NULL)
				{
					xQueueSendFromISR(Route_RxLink422_Qhd, &route_rx_link422_isr, NULL);
				}
			}
			rs422_isr_recvstate = RS422_RCVST_HEADER1;
			break;
			
		default:
			rs422_isr_recvstate = RS422_RCVST_HEADER1;
			break;
	}
}
